<template>
  <!-- 快捷返回 -->
  <custom-back></custom-back>

  <lay-card v-if="loading && bannerInfo && bannerInfo?.position == 'top'">
    <DcodeBanner
      v-bind="bannerInfo!.content || {}"
      :bannerData="bannerData"
    ></DcodeBanner>
  </lay-card>

  <!-- 搜索区域 -->
  <lay-card style="user-select: none">
    <custom-filter-form
      ref="queryFormRef"
      :model="queryFormValue"
      :schema="tableInfo.schema"
      :custom-json-schema="customJsonSchema"
      @on-query="table?.fetchData"
      @on-reset="table?.reset"
      @custom-operate="(schemaValue, item) => customJsonFun(schemaValue, item)"
      v-if="
        !pageloading &&
        tableInfo.schema &&
        JSON.stringify(tableInfo.schema) != '{}'
      "
    ></custom-filter-form>
  </lay-card>

  <lay-card class="table-main" v-if="tmpType == '1101'">
    <DynamicTable
      ref="table"
      :pageId="pageId"
      :query="route.query"
      :queryFormValue="queryFormValue"
      :data-request="getListData"
      v-model:columns="columns"
      v-bind="tableInfo"
      :queryFormRef="queryFormRef"
    >
    </DynamicTable>
  </lay-card>
  <lay-card class="table-main" v-if="tmpType == '1120'">
    <DcodeTab
      v-bind="tabInfo"
      :tabArr="tabArr"
      @fetchData="handleTaTableChange"
    >
      <template #table="{ tabValue, treeName }">
        <DynamicTable
          :pageId="pageId"
          ref="table"
          :query="route.query"
          :treeName="treeName"
          :treeKey="tabValue"
          :queryFormValue="queryFormValue"
          :data-request="getListData"
          v-model:columns="columns"
          v-bind="tableInfo"
          :queryFormRef="queryFormRef"
        >
        </DynamicTable>
      </template>
    </DcodeTab>
  </lay-card>

  <lay-card v-if="loading && bannerInfo && bannerInfo?.position == 'bottom'">
    <DcodeBanner
      v-bind="bannerInfo!.content || {}"
      :bannerData="bannerData"
    ></DcodeBanner>
  </lay-card>

  <lay-layer
    v-model="colLookupShow"
    :shade="false"
    :area="['80vw']"
    :btn="colAction"
  >
    <div class="layer-content">
      <custom-filter-form
        ref="popQueryFormRef"
        :model="popFormModel"
        :schema="popFormSchema"
        :custom-json-schema="popCustomSchema"
        @on-query="handleLayerFormQuery"
        @on-reset="handleLayerFormReset"
        v-if="popFormSchema && JSON.stringify(popFormSchema) != '{}'"
      ></custom-filter-form>

      <DynamicTable
        enableRadio
        ref="colLookupTable"
        :data-source="colLookupData"
        :columns="colLookupColumns"
        @row="handleLayerTableRow"
        :queryFormRef="popQueryFormRef"
      >
      </DynamicTable>
    </div>
  </lay-layer>
  <lay-loading v-if="pageloading"></lay-loading>
</template>

<script lang="ts" setup>
import { ref, watch, onMounted, nextTick, reactive } from "vue";
import { useRoute } from "vue-router";
import { getListData } from "@/api/module/commone";
import {
  interApi,
  interDatasourceApi,
  pageInfo,
  getTabData,
  getColServiceData,
  getColLookupData,
} from "@/api/module/login";
import { ShowMap } from "@/components/dynamic-table/src/hooks/tableMap";
import { useSystemStore } from "@/store/login";
import {
  isEmpty,
  isFunction,
  isNullOrUnDef,
  transformTemplate,
  isArray,
  isFormValue,
} from "@/utils";

// import DcodeBanner from "@/components/banner/index.vue";
import DcodeBanner from "@/components/banner/banner";
// import DcodeBannerDemo1 from "@/components/banner/demo1.vue";
import DcodeTab from "@/components/tab/index.vue";
// import CustomRang from "@/components/rang/index.vue";
import CustomBack from "./custom-back.vue";
import CustomFilterForm from "./custom-filter-form.vue";

const props = defineProps({
  pageId: {
    type: String,
    default: "",
  },
});

const route = useRoute();
// let pageId = (route.value.meta.pageId as string) || "";
// let pageGroup = (route.value.meta.pageGroup as number) || 0;
const colLookupShow = ref(false);
const colLookupData = ref([]);
const colLookupColumns = ref([]);
const colLookupTable = ref();
const pageloading = ref();
const cachePreLayer = reactive({
  schemaValue: null,
  item: null,
});

const handleLayerFormQuery = async () => {
  // await popQueryFormRef.value?.validate();
  customJsonFun(cachePreLayer.schemaValue, cachePreLayer.item);
};
const handleLayerFormReset = async () => {
  popFormModel.value = {};
  popFormSchema.value = {};
  await popQueryFormRef.value?.resetFields();
  customJsonFun(cachePreLayer.schemaValue, cachePreLayer.item);
};

const getColConfig = async (schemaValue: any) => {
  const type = schemaValue.disType || schemaValue.eleDisType;
  if (type === "71") {
    return getColLookupConf(schemaValue.id);
  } else if (type === "104") {
    return getColServiceConf(schemaValue.id);
  }
};
const customJsonFun = async (schemaValue: any, item) => {
  cachePreLayer.schemaValue = schemaValue;
  cachePreLayer.item = item;

  colLookupShow.value = true;

  currentFormItem.value = item;
  const type = schemaValue.disType || schemaValue.eleDisType;
  if (type === "71" || type === "104") {
    await getColConfig(schemaValue);
  }
};
//设置弹窗表格
const setModalTable = (dbCollection: any) => {
  colLookupData.value = dbCollection?.data;
  colLookupColumns.value = dbCollection?.tableInfo.fieldList
    .filter((_: { accessRight: number }) => _.accessRight >= 2)
    .map((_: any) => {
      return {
        ..._,
        key: _.code,
        title: _.name,
      };
    });

  colLookupTable.value.selectedKey =
    queryFormValue.value[currentFormItem.value] ?? "";
};

/**
 * 弹窗filter
 */
const popQueryFormRef = ref();
const popFormModel = ref({});
const popFormSchema = ref({});
const popCustomSchema = ref<string[]>([]);

const handleLayerTableRow = (row) => {
  colLookupTable.value.selectedKey = row.id;
};

// 获取服务列数据
const getServiceColumnData = async (
  apiFunction: (arg0: {
    funcCode: string;
    formId: string;
    columnId: string;
    clientMacro: string;
  }) => any,
  columnId: string,
) => {
  const { pageId } = props;

  await nextTick();

  const { page, formatValue } = colLookupTable.value;

  const queryParams = {
    PageIndex: page.current,
    PageSize: page.limit,
  };

  const values = await popQueryFormRef.value?.validate();

  // const searchParam = values.model.
  const searchParamArr: any[] = [];
  for (const key in values?.model || {}) {
    const type = popFormSchema.value[key] as any;
    const value = formatValue(values.model[key], type);

    isFormValue(value) &&
      searchParamArr.push({
        columnCode: key,
        filterType: type?.filterType || 1,
        // 当组件value为array时，转为以,分割的string
        value,
      });
  }

  const clientMacro = JSON.stringify({
    treeKey: "",
    treeName: "",
    appId: window._config.appId,
  });

  const params = {
    funcCode: pageId,
    formId: pageId,
    columnId,
    clientMacro,
    queryParam: JSON.stringify(queryParams),
    searchParam: JSON.stringify(searchParamArr),
  };

  const res = (await apiFunction(params)).data;
  currentFormConf.value = {
    tableKey: res.tableKey,
    displayCol: res.displayCol,
    searchInfo: res.searchInfo,
  };

  // get layer json-schema-form config
  if (isArray(res.filter) && isArray(res.dbCollection.tableInfo.fieldList)) {
    const filedList = res.dbCollection.tableInfo.fieldList.reduce(
      (pre, next) => {
        pre[next.code] = next;
        return pre;
      },
      {},
    );

    // 当弹窗已经打开，不重新获得表单数据
    // 防止表单model值重新赋值
    if (isEmpty(popFormSchema.value)) {
      const { formModel, formSchema, customSchema } =
        await formatFilterFormBody(res.filter, filedList);

      popFormModel.value = formModel;
      popFormSchema.value = formSchema;
      popCustomSchema.value = customSchema;
    }
  }

  const { dbCollection } = res;
  if (dbCollection && !isEmpty(dbCollection)) {
    setModalTable(dbCollection);
  }
};

// 获取服务列配置
const getColLookupConf = async (columnId: string) => {
  return getServiceColumnData(getColLookupData, columnId);
};

// 获取服务列配置
const getColServiceConf = async (columnId: string) => {
  return getServiceColumnData(getColServiceData, columnId);
};
//搜索弹窗当前点击项
const currentFormItem = ref<any>();
//搜索弹窗点击配置
const currentFormConf = ref({});
const colAction = ref([
  {
    text: "确认",
    callback: () => {
      let res = colLookupTable.value?.getCheckData();
      queryFormValue.value[currentFormItem.value] =
        res[0]?.[currentFormConf.value?.tableKey];
      queryFormValue.value[`${currentFormItem.value}-copyText`] =
        res[0]?.[currentFormConf.value?.displayCol];
      colLookupShow.value = false;
    },
  },
  {
    text: "取消",
    callback: () => {
      colLookupShow.value = false;
      // layer.confirm("取消操作", { shade: false });
    },
  },
]);
//getCheckData
const customJsonSchema = ref<any>([]);

const systemStore = useSystemStore();
const tmpType = ref();
/**
 * 表格及搜索props
 */
const table = ref();
const queryFormValue = ref({});
const tableInfo = ref<any>({
  schema: {},
  btnsArr: [],
  tmp: "",
});
const queryFormRef = ref<any>();
/**
 * banner
 */
const bannerInfo = ref<any>({});
// const template = ref("");
const bannerData = ref({});
const loading = ref(false);
const tabInfo = ref<any>({});
const tabArr = ref([]);

// format banner data
const handleformatBanner = async (bannerSetting) => {
  const { pageId } = props;

  bannerInfo.value = JSON.parse(bannerSetting);
  if (!isEmpty(bannerInfo.value?.methodType)) {
    const apiUrl = (type: "1" | "2") => {
      switch (type) {
        case "1":
          return interApi;
        case "2":
          return interDatasourceApi;
        default:
      }
    };

    const callback = apiUrl(bannerInfo.value?.methodType);

    if (isFunction(callback)) {
      const response = await callback({
        pageId: pageId,
        appId: window._config.appId,
        methodId: bannerInfo.value?.methodId,
        data: {},
      });
      bannerData.value = response.data || {};
    }
  } else {
    bannerData.value = {};
  }
  loading.value = true;
  // template.value = transformTemplate(JSON.parse(bannerSetting));
};

// 渲染整数输入框处理
const handleInt = (code, formModel) => {
  return {
    listeners: {
      onInput: (v) => {
        const intValue = !Number(v) ? "" : v.split(".")[v];
        formModel[code] = intValue;
      },
    },
  };
};

const handleCustomRenderProp = (type, item, formModel) => {
  // 弹窗
  if (["71", "104"].includes(type)) {
    return { slots: { customRender: item.columnCode } };
  }

  // 处理filterType为5场景
  // 渲染日期范围或输入框范围
  if ([5].includes(item.filterType)) {
    const config = { slots: { customRender: "customRange" } };
    return config;
  }

  // 整数
  if (["40"].includes(type)) {
    return handleInt(item.columnCode, formModel);
  }

  return {};
};

// format json-schema-from default model
const formatFilterFormDefaultValue = (defaultValue, type) => {
  // checkbox 需要转成 boolean
  if (["30", "31"].includes(type)) {
    return !!Number(defaultValue);
  }

  return defaultValue;
};

const formatFilterFormBody = async (filter, fieldList) => {
  const formModel = {};
  const formSchema = {};
  const customSchema = [] as string[];

  filter.sort((a, b) => a.orderId - b.orderId);

  for (const item of filter) {
    const fieldInfo = fieldList[item.columnCode] || {};
    // render type
    const type =
      (item.columnCode.includes(",") && "10") ||
      item.disType ||
      fieldInfo.eleDisType;
    const schemaValue = ShowMap.get(type);

    const isDisTypeIncluded = ["71", "104"].includes(type);

    if (isDisTypeIncluded) {
      customSchema.push(item.columnCode);
    }

    // set json-schema-form model props
    if (item.defaultValue) {
      formModel[item.columnCode] = formatFilterFormDefaultValue(
        item.defaultValue,
        type,
      );
      if (isDisTypeIncluded) {
        formModel[`${item.columnCode}-copyText`] = item.defaultValueName;
      }
    }

    if (ShowMap.has(type)) {
      const commonProps = {
        ...item,
        ...fieldInfo,
        ...schemaValue,
        label: item.aliasName || fieldInfo.name,
      };

      // 获取自定义渲染配置
      const customRenderProp = handleCustomRenderProp(type, item, formModel);

      // filter 为 6|7 开启多选
      const multipleConfig = [6, 7].includes(item.filterType)
        ? {
            multiple: true,
            showSearch: true,
          }
        : {};

      formSchema[item.columnCode] = {
        ...commonProps,
        ...customRenderProp,
        required: !!item?.required || schemaValue.required || false,
        requiredErrorMessage: "请输入查询内容",
        props: {
          "allow-clear": true,
          placeholder: isDisTypeIncluded
            ? fieldInfo.name
            : `${schemaValue.props?.placeholder}${item.aliasName || fieldInfo.name}`,
          type: schemaValue.props.type,
          options:
            (await setOPtions(
              schemaValue.props?.options,
              ["70", "101"].includes(type)
                ? fieldInfo.id
                : fieldInfo.codeTypeId,
              type,
            )) || [], // 使用之前定义的options，如果它是undefined则使用一个空数组
          ...multipleConfig,
        },
      };
    }
  }

  // 设置filter form operate
  formSchema["devOperate"] = {
    slots: {
      customRender: "devOperate",
    },
    colProps: {
      md: 6,
    },
  };

  const keys = Object.keys(formSchema);

  keys.forEach((item, index) => {
    if (index >= 3 && index !== keys.length - 1) {
      formSchema[item].hidden = true;
    }
  });

  return {
    formModel,
    formSchema,
    customSchema,
  };
};

/**
 * 页面配置
 */
const getPageConf = async () => {
  const { pageId } = props;

  pageloading.value = true;
  let res = (await pageInfo(pageId)).data;
  tmpType.value = res.tmp;
  const search = res.search;

  // const cacheSchema: any = {};
  if (!isEmpty(search?.filter) && !isNullOrUnDef(search?.filter)) {
    const { formModel, formSchema, customSchema } = await formatFilterFormBody(
      search.filter,
      search.fieldInfo,
    );

    queryFormValue.value = formModel;
    tableInfo.value.schema = formSchema;
    customJsonSchema.value = customSchema;
  }

  if (res.gridInfo) {
    Object.assign(tableInfo.value, JSON.parse(res.gridInfo));
  }
  if (res.btns) {
    res.btns.sort(
      (a: { orderId: number }, b: { orderId: number }) => a.orderId - b.orderId,
    );
    tableInfo.value.btnsArr = res.btns;
  }

  if (res.bannerSetting) {
    await handleformatBanner(res.bannerSetting);
  }

  //页签处理
  if (res.tmp == "1120" && res.treeInfo) {
    tabInfo.value = JSON.parse(res.treeInfo);
    if (tabInfo.value?.codeDataSource) {
      tabArr.value =
        systemStore.codeTableList.get(tabInfo.value?.codeDataSource) || [];
    } else {
      tabArr.value = (
        await getTabData({
          pageId,
          clientMacro: "",
        })
      ).data;
    }
  }
  pageloading.value = false;
};

/**
 * 码表处理
 */
const setOPtions = async (
  options: never[],
  codeTypeId: any,
  type: string = "",
) => {
  const { pageId } = props;

  // 定义获取数据和映射结果的函数
  const fetchAndMapData = async (apiFunction: Function, params: any) => {
    const res = (await apiFunction(params)).data;
    return res.dbCollection.data.map((item) => ({
      value: item[res.tableKey],
      label: item[res.searchCols],
    }));
  };

  // 根据type选择不同的API和params
  let params = {
    funcCode: pageId,
    formId: pageId,
    columnId: codeTypeId,
    clientMacro: JSON.stringify({
      treeKey: "",
      treeName: "",
      appId: window._config.appId,
    }),
  };
  switch (type) {
    case "70":
      return await fetchAndMapData(getColLookupData, params);

    case "101":
      return await fetchAndMapData(getColServiceData, params);

    default:
      if (codeTypeId) {
        try {
          const codeList = systemStore.codeTableList.get(codeTypeId);

          return codeList
            .map((code: { name: any; code: any }) => ({
              ...code,
              label: code.name,
              value: code.code,
              skin: "primary",
            }))
            .sort((a, b) => a.orderId - b.orderId);
        } catch (error) {
          return [];
        }
      } else {
        return options || [];
      }
  }
};

const handleTaTableChange = async () => {
  await nextTick();
  table.value.fetchData();
};

onMounted(async () => {
  !systemStore.codeTableList.size && (await systemStore.codeTableInfo());
  // getPageConf();
});

const columns = ref([]);

watch(
  () => props.pageId,
  async (value) => {
    if (value) {
      await getPageConf();
      table.value.fetchData();
    }
  },
  { immediate: true },
);
</script>

<style scoped lang="less">
.layer-content {
  padding: 16px;
}
</style>
